package com.it.filter;

import cn.hutool.core.util.StrUtil;
import com.it.config.LoginFailureHandler;
import com.it.exception.CaptchaException;
import com.it.utisl.RedisUtil;
import com.it.vo.Const;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 用户登录时校验验证码，如果验证码不正确，则通过登录失败处理器返回相应的错误信息
 *
 * @author: Coke
 * @DateTime: 2023/11/19/15:01
 **/
@Slf4j
@Component
public class CaptchaFilter extends OncePerRequestFilter {
    
    private final String loginUrl = "/login";
    
    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private LoginFailureHandler loginFailureHandler;
    
    @Override
    // 进行过滤操作
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取请求的URL
        String url = request.getRequestURI();
        
        // 判断是否为登录请求且为POST请求
        if (loginUrl.equals(url) && "POST".equals(request.getMethod())) {
            log.info("获取到login链接，正在校验验证码 -- " + url);
            try {
                // 校验验证码
                validate(request);
            } catch (CaptchaException e) {
                log.info(e.getMessage());
                
                // 将 CaptchaException 转换为 AuthenticationException
                AuthenticationException authenticationException = new AuthenticationServiceException(e.getMessage(), e);
                
                // 交给登录失败处理器处理
                loginFailureHandler.onAuthenticationFailure(request, response, authenticationException);
            }
        }
        
        // 继续处理请求
        filterChain.doFilter(request, response);
    }
    
    // 验证验证码
    private void validate(HttpServletRequest request) throws CaptchaException {
        // 从请求参数中获取验证码和key
        String code = request.getParameter("code");
        String key = request.getParameter("key");
        
        // 判断验证码和key是否为空
        if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
            throw new CaptchaException("验证码不能为空");
        }
        
        // 从Redis中获取存储的验证码
        String storedCode = (String) redisUtil.hget(Const.CAPTCHA_KEY, key);
        
        // 判断输入的验证码是否正确
        if (!StrUtil.equals(code, storedCode)) {
            throw new CaptchaException("验证码不正确");
        }
        
        // 验证通过，删除Redis中的验证码
        redisUtil.hdel(Const.CAPTCHA_KEY, key);
    }
}
